package com.bsj.power.pls.queue;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bsj.consumerQ.function.HandleRunT;
import com.bsj.consumerQ.method.QueueAndRunT;
import com.bsj.power.common.config.cached.LocationDeviceCached;
import com.bsj.power.common.config.cached.RedisCached;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.config.rocketmq.producer.BaseMqPushUtil;
import com.bsj.power.common.constant.AlarmEnum;
import com.bsj.power.common.constant.MqTopicAndTagConstants;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.constant.UWBPosConstant;
import com.bsj.power.common.def.dto.cardReport.BindCardDTO;
import com.bsj.power.common.def.dto.locationDevice.TagMsgDTO;
import com.bsj.power.common.def.entity.HighRise;
import com.bsj.power.common.def.entity.alarmReport.AlarmReport;
import com.bsj.power.common.def.entity.job.WorkPersonnel;
import com.bsj.power.common.def.entity.locationDevice.LocationDevice;
import com.bsj.power.common.def.entity.locationDevice.LocationDeviceLog;
import com.bsj.power.common.def.entity.personnel.Personnel;
import com.bsj.power.common.def.vo.WebSocketMsgVO;
import com.bsj.power.common.def.vo.pls.httpVo.HttpTagPosVO;
import com.bsj.power.common.mapper.LocationDeviceLogMapper;
import com.bsj.power.common.util.ExceptionUtil;
import com.bsj.power.pls.config.cached.HighRiseCached;
import com.bsj.power.pls.file.saveData.SaveDataBaseUntil;
import com.bsj.power.pls.queue.service.impl.QueuePathAlarmImpl;
import com.bsj.power.pls.queue.service.impl.QueuePathRemainAlarmImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description 标签数据队列
 * @time 2024/5/21 15:54
 */
@Slf4j
@Component
public class MsgQueue extends QueueAndRunT<TagMsgDTO> {

    @Autowired
    private RedisCached redisCached;

//    @Autowired
//    private WebsocketService websocketService;

    @Autowired
    private SaveDataBaseUntil saveDataBaseUntil;

    @Autowired
    private AlarmQueue alarmQueue;

    @Autowired
    private PathAlarmQueue pathAlarmQueue;

    @Autowired
    private QueuePathAlarmImpl queuePathAlarm;

    @Autowired
    private QueuePathRemainAlarmImpl queuePathRemainAlarm;

//    @Autowired
//    private JobSignInQueue jobSignInQueue;

    @Autowired
    private BaseMqPushUtil baseMqPushUtil;

    @Autowired
    private SosAlarmQueue sosAlarmQueue;

    @Autowired
    private LocationDeviceCached locationDeviceCached;

    @Resource
    private LocationDeviceLogMapper locationDeviceLogMapper;

    public void start() {
        start("msgQueue", new HandleRunT<TagMsgDTO>() {
            @Override
            public void doRun(List<TagMsgDTO> list) {
                if (CollectionUtils.isEmpty(list)) {
                    return;
                }
                try {
                    //按照设备号来分，需要进行数据筛选过滤
                    Map<String, List<TagMsgDTO>> snMaps = list.stream().collect(Collectors.groupingBy(TagMsgDTO::getSn));
                    snMaps.forEach((key, value) -> {
                        //将同个设备号的数据，按照10位时间戳去重后进行保存,每个设备，每秒钟只保存一条数据
                        Map<Long, TagMsgDTO> map = value.stream().collect(Collectors.toMap(TagMsgDTO::getNow,
                                Function.identity(), (existing, replacement) -> existing));
                        //将数据按照接收的时间排序，避免数据错乱
                        List<TagMsgDTO> msgDTOList = new ArrayList<>(map.values());
                        msgDTOList.sort(Comparator.comparing(TagMsgDTO::getNow));
                        //数据处理
                        for (TagMsgDTO tagMsgDTO : msgDTOList) {
                            int type = tagMsgDTO.getType();
                            //设备号
                            String sn = tagMsgDTO.getSn();
                            String data = tagMsgDTO.getData();
                            long id = tagMsgDTO.getId();
                            switch (type) {
                                case UWBPosConstant.MSG_TYPE_STATUS:
//                                    log.info("状态数据:" + data);
//                                    statusDataHandle(sn, data);
                                    break;
                                case UWBPosConstant.MSG_TYPE_POS:
//                                    log.info("位置数据:" + data);
                                    HttpTagPosVO httpTagPosVO = JSONObject.parseObject(data, HttpTagPosVO.class);
                                    httpTagPosVO.setId(id);
                                    //先要判断定位引擎发送过来的位置点是否在室内,如果不在室内,则丢掉，使用卫星定位的位置点信息
                                    int mapId = httpTagPosVO.getMapId();
                                    int posType = httpTagPosVO.getPosType();
                                    if (posType == 0) {
//                                        HighRise highRise = HighRiseCached.getHigh(mapId);
//                                        if (highRise == null) {
//                                            //设备变为室外后,保存使用RTK定位标识,切换使用RTK定位信息
//                                            redisCached.set(UWBPosConstant.REDIS_UWB_GPS_POS_FLAG_KEY + sn, "2", 5);
//                                            break;
//                                        }
//                                        //变成室内后则删除室外定位标识,切换回室内定位
//                                        redisCached.del(UWBPosConstant.REDIS_UWB_GPS_POS_FLAG_KEY + sn);
                                        String gpsPosFlag = redisCached.get(UWBPosConstant.REDIS_UWB_GPS_POS_FLAG_KEY + sn);
                                        if (gpsPosFlag != null) {
                                            //设备变为室外定位后，只保留微信定位数据
                                            break;
                                        }
                                    }
                                    if (httpTagPosVO != null) {
                                        double[] pos = httpTagPosVO.getPos();
                                        if (pos == null) {
                                            //过滤位置异常数据
                                            log.warn("设备位置数据异常sn: {}, pos: {}", sn, pos);
                                            continue;
                                        }
                                        if (pos.length >= 3) {
                                            double x = NumberUtil.round(pos[0], 2).doubleValue();
                                            double y = NumberUtil.round(pos[1], 2).doubleValue();
                                            double z = NumberUtil.round(pos[2], 2).doubleValue();
                                            httpTagPosVO.setReducePos(new double[]{x, y, z});
                                        }
                                        sn = httpTagPosVO.getSn();

                                        //同步给到网页展示
                                        WebSocketMsgVO webSocketMsgVO = WebSocketMsgVO.builder()
                                                .msgType(NumericalConstants.ONE)
                                                .obj(httpTagPosVO)
                                                .build();
                                        String jsonString = JSON.toJSONString(webSocketMsgVO);
                                        baseMqPushUtil.sendTopicBytes(MqTopicAndTagConstants.SYSTEM_WEB_SERVER_CHANGE_TOPIC,
                                                MqTopicAndTagConstants.SYSTEM_WEB_PRODUCT_CHANGE_TAG, jsonString.getBytes());

                                        redisCached.set(UWBPosConstant.REDIS_TAG_POS_KEY + sn, httpTagPosVO);
                                        //先只保存位置信息数据
//                                        log.info("保存位置数据:" + httpTagPosVO);
                                        saveDataBaseUntil.push(JSON.toJSONBytes(httpTagPosVO));
                                        try {
                                            queuePathAlarm.doRun(httpTagPosVO);
//                                    jobSignInQueue.push(httpTagPosVO);
                                            // 人员长期停留报警
                                            queuePathRemainAlarm.doRun(httpTagPosVO);
                                        } catch (Exception e) {
                                            log.error("alarmQueue写入数据失败:" + ExceptionUtil.getStackStr(e));
                                        }
                                    }
                                    break;
                                case UWBPosConstant.MSG_TYPE_EVENT:
                                    JSONObject obj = JSON.parseObject(data);
                                    String name = obj.getString("name");
                                    if (!"TransmitData".equalsIgnoreCase(name)) {
                                        break;
                                    }
                                    //只处理透传数据
                                    log.info("事件信息: {}", data);
                                    try {
                                        sosAlarmQueue.push(tagMsgDTO);
                                    } catch (Exception e) {
                                        log.error("sosAlarmQueue写入数据失败:" + ExceptionUtil.getStackStr(e));
                                    }
                                    break;
                            }
                        }
                    });
                } catch (Exception e) {
                    log.error(ExceptionUtil.getStackStr(e));
                    return;
                }
            }
        });
    }

    /**
     * 标签状态数据处理
     *
     * @param sn   设备号
     * @param data 标签状态数据
     * @return void
     * @author ljx
     * @time 2024/12/5 19:42
     */
//    private void statusDataHandle(String sn, String data) {
//        JSONObject jsonObject = JSONObject.parseObject(data);
//        Boolean online = jsonObject.getBoolean("online");
//        if (online != null) {
//            LocationDevice locationDevice = locationDeviceCached.hgetLocationDeviceInfo(sn);
//            if (locationDevice == null) {
//                return;
//            }
//            //非基站设备
//            if (!locationDevice.getDeviceType().equals(NumericalConstants.ONE)) {
//                return;
//            }
//            LocationDeviceLog locationDeviceLog = new LocationDeviceLog(locationDevice);
//            if (online) {
//                locationDeviceLog.setType(NumericalConstants.TWO);
//            } else {
//                locationDeviceLog.setType(NumericalConstants.ONE);
//            }
//            locationDeviceLogMapper.insert(locationDeviceLog);
//        }
//    }

}
